// Copyright (C) 1953-2022 NUDT
// Verilog module name - command_parse_and_encapsulate_rwc
// Version: V4.0.0.20220915
// Created:
//         by - fenglin 
////////////////////////////////////////////////////////////////////////////
// Description:
//         
///////////////////////////////////////////////////////////////////////////

`timescale 1ns/1ps

module command_parse_and_encapsulate_rwc
(
        i_clk,
        i_rst_n,
        
        iv_addr,                         
        iv_wdata,                        
        i_wr,         
        i_rd,         
        o_wr,          
        ov_addr,       
        ov_rdata,
        
        iv_st_overflow_error_cnt,
        iv_st_underflow_error_cnt,
        iv_receive_slot_error_cnt,
        ov_port_mode  ,
        ov_ram_addr   , 
        ov_ram_wdata  ,
        o_ram_wr      ,
        iv_ram_rdata  ,
        o_ram_rd              
);

// I/O
// clk & rst
input                   i_clk       ;
input                   i_rst_n     ;

input       [18:0]      iv_addr     ;                         
input       [31:0]      iv_wdata    ;                        
input                   i_wr        ;         
input                   i_rd        ;         

output reg              o_wr        ;          
output reg [18:0]       ov_addr     ;       
output reg [31:0]       ov_rdata    ;

input      [15:0]       iv_st_overflow_error_cnt;
input      [15:0]       iv_st_underflow_error_cnt;
input      [15:0]       iv_receive_slot_error_cnt;
output reg [7:0]        ov_port_mode  ;
output reg [9:0]        ov_ram_addr   ;
output reg [19:0]       ov_ram_wdata  ;
output reg              o_ram_wr      ;
input      [19:0]       iv_ram_rdata  ;
output reg              o_ram_rd      ;   
            
always@(posedge i_clk or negedge i_rst_n)begin
    if(!i_rst_n) begin       
        ov_port_mode   <= 8'h0 ; 
        
        ov_ram_addr    <= 10'b0;   
        ov_ram_wdata   <= 20'b0;
        o_ram_wr       <= 1'b0 ;
        o_ram_rd       <= 1'b0 ;
    end
    else begin
        if(i_wr)begin//write
            if(iv_addr <= 19'h0_03ff)begin
                ov_ram_addr    <= iv_addr;   
                ov_ram_wdata   <= {iv_wdata[31],iv_wdata[18:0]};
                o_ram_wr       <= 1'b1;
                o_ram_rd       <= 1'b0;
            end
            else if(iv_addr == 19'h0_1000)begin
                ov_port_mode <= iv_wdata[7:0];
                
                o_ram_wr     <= 1'b0;
                o_ram_rd     <= 1'b0;                
            end
            else begin
                o_ram_wr       <= 1'b0        ;
                o_ram_rd       <= 1'b0        ;
            end
        end
        else if(i_rd)begin//read
            if(iv_addr <= 19'h0_03ff)begin
                ov_ram_addr    <= iv_addr;   
                ov_ram_wdata   <= 20'b0;
                o_ram_wr       <= 1'b0;
                o_ram_rd       <= 1'b1;
            end
            else if(iv_addr == 19'h0_1000)begin
                o_ram_wr       <= 1'b0        ;
                o_ram_rd       <= 1'b0        ;
            end
            else begin
                o_ram_wr       <= 1'b0;
                o_ram_rd       <= 1'b0;       
            end
        end
        else begin
            o_ram_wr       <= 1'b0        ;
            o_ram_rd       <= 1'b0        ;
        end        
    end
end 
reg  [2:0]  rv_istram_rden;
reg  [9:0]  rv_istram_raddr0;
reg  [9:0]  rv_istram_raddr1;
reg  [9:0]  rv_istram_raddr2;
always@(posedge i_clk or negedge i_rst_n)begin
    if(!i_rst_n) begin
        rv_istram_rden   <= 3'b0;
        rv_istram_raddr0 <= 10'b0;
        rv_istram_raddr1 <= 10'b0;
        rv_istram_raddr2 <= 10'b0;
    end
    else begin
        rv_istram_rden   <= {rv_istram_rden[1:0],o_ram_rd};
        rv_istram_raddr0 <= ov_ram_addr;
        rv_istram_raddr1 <= rv_istram_raddr0;
        rv_istram_raddr2 <= rv_istram_raddr1;        
    end
end
always@(posedge i_clk or negedge i_rst_n)begin
    if(!i_rst_n) begin
        o_wr            <= 1'b0 ;
        ov_addr         <= 19'b0;
        ov_rdata        <= 32'b0;
    end
    else begin
        if(rv_istram_rden[2])begin//get data from ram
            o_wr            <= 1'b1;
            ov_addr         <= {9'b0,rv_istram_raddr2};
            ov_rdata        <= {iv_ram_rdata[19],12'b0,iv_ram_rdata[18:0]};
        end
        else if(i_rd && (iv_addr == 19'h0_1000))begin
            o_wr            <= 1'b1;
            ov_addr         <= iv_addr;
            ov_rdata        <= {24'b0,ov_port_mode};
        end
        else if(i_rd && (iv_addr == 19'h0_1001))begin
            o_wr            <= 1'b1;
            ov_addr         <= iv_addr;
            ov_rdata        <= {iv_st_underflow_error_cnt,iv_st_overflow_error_cnt};
        end 
        else if(i_rd && (iv_addr == 19'h0_1002))begin
            o_wr            <= 1'b1;
            ov_addr         <= iv_addr;
            ov_rdata        <= {16'b0,iv_receive_slot_error_cnt};
        end         
        else begin
            o_wr            <= 1'b0 ;
            ov_addr         <= 19'b0;
            ov_rdata        <= 32'b0;
        end        
    end
end         
endmodule